package com.grm.handler;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 文件下载处理器
 * 用于处理文件下载请求的处理器，继承自SimpleChannelInboundHandler
 * 专注于处理HttpRequest对象，简化了通道读取操作的处理
 */
public class FileDownloadHandler extends SimpleChannelInboundHandler<HttpRequest> {

    private static final String UPLOAD_DIR = "uploaded_files"; // 配置化的文件路径

    /**
     * 处理接收到的HttpRequest
     * 根据请求的URI查找对应的文件，并发送文件给客户端
     * 如果文件不存在，则发送404 NOT FOUND响应
     *
     * @param ctx 通道处理上下文，用于写入和刷新数据到通道
     * @param msg 接收到的HttpRequest对象，包含请求信息
     * @throws Exception 抛出异常时需要处理
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception {
        // 获取请求的URI
        String uri = msg.uri();

        // 构建文件路径并验证路径合法性
        Path basePath = Paths.get(UPLOAD_DIR);
        Path filePath = basePath.resolve(uri).normalize();
        if (!filePath.startsWith(basePath)) {
            sendErrorResponse(ctx, HttpResponseStatus.FORBIDDEN, "Invalid path");
            return;
        }

        // 创建File对象
        File file = filePath.toFile();

        // 检查文件是否存在且为文件类型
        if (file.exists() && file.isFile()) {
            try (FileInputStream fileInputStream = new FileInputStream(file)) {
                byte[] bytes = new byte[(int) file.length()];
                fileInputStream.read(bytes);

                // 设置响应头
                FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                        Unpooled.wrappedBuffer(bytes));
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/octet-stream");
                response.headers().set(HttpHeaderNames.CONTENT_DISPOSITION, "attachment; filename=" + file.getName());

                ctx.writeAndFlush(response);
            } catch (IOException e) {
                sendErrorResponse(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR, "Failed to read file");
            }
        } else {
            // 文件不存在
            sendErrorResponse(ctx, HttpResponseStatus.NOT_FOUND, "File not found");
        }
    }

    private void sendErrorResponse(ChannelHandlerContext ctx, HttpResponseStatus status, String message) {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status,
                Unpooled.copiedBuffer(message.getBytes()));
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
        ctx.writeAndFlush(response);
    }
}